package com.life.notes.config.utils;

import java.util.concurrent.*;

/**
 * 线程池配置
 * @author lishuqian
 * @date 2020/6/15
 */
public class ThreadPoolUtil {
    /**
     * 根据cpu的数量动态的配置核心线程数和最大线程数
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    /**
     * 核心线程数 = CPU核心数 + 1
     */
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    /**
     * 线程池最大线程数 = CPU核心数 * 2 + 1
     */
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    /**
     * 最大工作队列
     */
    private static final int MAX_WORK_QUEUES = 1024;
    /**
     * 非核心线程闲置时超时10s
     */
    private static final int KEEP_ALIVE = 10;
    /**
     *  线程池的对象
     */
    private static ThreadPoolExecutor executor;

    private ThreadPoolUtil(){}
    /**
     * 获取线程池
     * @return
     */
    public static ThreadPoolExecutor getInstance() {
        if (executor != null) {
            return executor;
        } else {
            synchronized (ThreadPoolUtil.class) {
                if (executor == null) {
                    executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
                            new LinkedBlockingQueue<>(MAX_WORK_QUEUES), new ThreadPoolExecutor.CallerRunsPolicy());
                }
                return executor;
            }
        }
    }

    /**
     * 无返回值直接执行
     * @param runnable
     */
    public static void execute(Runnable runnable){
        getInstance().execute(runnable);
    }

    /**
     * 返回值直接执行
     * @param callable
     */
    public static <T> Future<T> submit(Callable<T> callable){
        return getInstance().submit(callable);
    }

    /**
     * 获取当前线程池线程数量
     * @return
     */
    public static int getSize() {
        return getInstance().getPoolSize();
    }

    /**
     * 获取当前活动的线程数量
     * @return
     */
    public static int getActiveCount() {
        return getInstance().getActiveCount();
    }

    /**
      * 获取空闲线程数
      * @return
      */
    public static int getFreeThreadNum() {
        int freeNum = getInstance().getCorePoolSize() -getInstance().getActiveCount();
        return freeNum;
    }
}